package org.momo.rpc.springboot.starter.bootstrap;

import org.momo.rpc.constant.LoadBalanceKey;
import org.momo.rpc.springboot.starter.annotion.RpcMethod;
import org.momo.rpc.springboot.starter.annotion.RpcReference;
import org.momo.rpc.proxy.ServiceProxyFactory;
import org.momo.rpc.bootstrap.model.ReferenceMetaInfo;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class RpcServiceProxyInjector implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class<?> beanClass = bean.getClass();
        Field[] declaredFields = beanClass.getFields();

        for (Field field : declaredFields) {
            if (field.isAnnotationPresent(RpcReference.class)) {
                RpcReference rpcReference = field.getAnnotation(RpcReference.class);
                field.setAccessible(true);

                Map<String, LoadBalanceKey> loadBalanceKeyMap = new HashMap<>();
                for(RpcMethod rpcMethod : rpcReference.methodConfigs()) {
                    loadBalanceKeyMap.put(rpcMethod.methodName(), LoadBalanceKey.valueOf(rpcMethod.loadBalancer().name()));
                }

                ReferenceMetaInfo referenceMetaInfo = new ReferenceMetaInfo(field.getType(), rpcReference.serviceName(), rpcReference.serviceVersion(), loadBalanceKeyMap);
                Object proxy = ServiceProxyFactory.getProxy(referenceMetaInfo);

                try {
                    field.set(bean, proxy);
                    field.setAccessible(false);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }

}
